/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package music.types;

import java.awt.FontMetrics;
import java.awt.Toolkit;
import java.util.TreeMap;
import music.SpacingOptions;
import music.global.CharacterMap;

/**
 *  
 * @author TJ
 */
public class MidiNote implements Comparable{
    private boolean renderSharpFlat=false;
    private String name;
    private int value;
    public static TreeMap<String,MidiNote> NotesByName=new TreeMap<String,MidiNote>();
    public static TreeMap<Integer,MidiNote> NotesByValue=new TreeMap<Integer,MidiNote>();
    public MidiNote(int val,String n) {
        name=n;
        value=val;
    }
    public boolean equals(Object e) {
        try{
            return this.equals((MidiNote)e);
        }catch(ClassCastException e2){return false;}
    }
    public boolean equals(MidiNote n){
        return enharmonicEquals(n) && name.equals(n.getName());
    }
    public boolean enharmonicEquals(MidiNote n){
        return value==n.getMidi();
    }
    /*public MidiNote getOctave(int o, String note) {
        MidiNote n=MidiNote.getByName(note);
        return new MidiNote(n.getMidi()+12*o,n.getName());
    }*/
    public String toString() {
        return name;
    }
    public static int getStaffLocation(int noteval,ClefType c){
        MidiNote n=MidiNote.getBaseNote(noteval);
        int baseloc=n.getStaffLocation(c);
        if(n.getMidi()>noteval) {
            while(n.getMidi()>noteval) {
                noteval+=12;
                baseloc-=8;
            }
        } else if(n.getMidi()<noteval) {
            while(n.getMidi()<noteval) {
                noteval-=12;
                baseloc+=8;
            }
        }
        return baseloc;
        
    }
    public boolean getRenderAccidental(){return this.renderSharpFlat;}
    public void setRenderAccidental(boolean f) { this.renderSharpFlat=f; }
    public int getStaffLocation(ClefType c) {
        int noteval=this.getName().toUpperCase().charAt(0);
        return noteval-(c.getBaseLine()+"").toUpperCase().charAt(0);
    }
    public String getName(){return name;}
    public int getMidi(){return value;}
    public int getAccidentalWidth(SpacingOptions s) {
        FontMetrics m=Toolkit.getDefaultToolkit().getFontMetrics(s.getRenderFont("OpusRegular"));
        return m.stringWidth(getAccidental());
    }
    public String getAccidental() {
        if(name.length()==1) {
            if(!renderSharpFlat){return "";}
            return ""+CharacterMap.NATURAL;
        }
        String name2=this.name.substring(1);
        name2=name2.replace("bb", ""+CharacterMap.DOUBLE_FLAT);
        name2=name2.replace('*', (char)CharacterMap.DOUBLE_SHARP);
        name2=name2.replace('b', CharacterMap.FLAT);
        name2=name2.replace('#', CharacterMap.SHARP);
        return name2;
        
    }
    public static MidiNote getByName(String n) {return NotesByName.get(n);}
    public static MidiNote getByValue(Integer n) {return NotesByValue.get(n);}
    public static MidiNote getBaseNote(int noteval){
        while(noteval>71) {
            noteval-=12;
        }
        while(noteval<60) {
            noteval+=12;
        }
        return MidiNote.getByValue(noteval);
    }
    public MidiNote shiftOctave(int oct,boolean up) {
        int value=0;
        if(up){value=this.value+12*oct;}
        else{value=this.value-12*oct;}
        return new MidiNote(value,name);
    }
    public void shiftOctave(boolean up) {
        if(up){value+=12;}
        else{value-=12;}
    }
    public void shiftNote(int steps){   
        value+=steps;
        name=MidiNote.getBaseNote(value).getName();
    }
    public MidiNote getIntervalAbove(MidiNote m, Interval v){
        int noteval=6;//m.getMidi()+v.getInterval();
        
        return MidiNote.getBaseNote(noteval);
    }
    public MidiNote getIntervalBelow(MidiNote m,Interval v){
        int noteval=6;//m.getMidi()-v.getInterval();
        return MidiNote.getBaseNote(noteval);
    }
    public boolean enharmonicallyEquivalent(MidiNote n) {return value==n.getMidi();}
    /*public static boolean enharmonicEquivalent(String a,String b){
        a=a.toUpperCase();b=b.toUpperCase();
        
    }
    public static String getNameFromValue(){}
    public static int getBaseValueFromName(String s){
        for(int i=1; i<s.length();i++){
            if(s.charAt(i)){
                
            }
        }
    }*/

    @Override
    public int compareTo(Object o) {
        MidiNote tmp=((MidiNote)o);
        return this.getMidi()-((MidiNote)o).getMidi();
    }
}
